Rework GtkTextView cursor code.
authorPaolo Borelli <pborelli@gnome.org>
Sat, 26 Nov 2011 22:48:10 +0000 (23:48 +0100)
committerPaolo Borelli <pborelli@gnome.org>
Thu, 1 Dec 2011 00:22:39 +0000 (01:22 +0100)
Move the handling of primary/secondary cursors to gtktextdisplay, which
makes code simpler and more consistent to how GtkLabel and GtkEntry
draw cursors, which is useful in preparation to further refactoring.

https://bugzilla.gnome.org/show_bug.cgi?id=640317

gtk/gtktextdisplay.c
gtk/gtktextlayout.c
gtk/gtktextlayout.h

index 360f515d50b53de33bb757b9509cb8488d22a07a..6911dae0ee089bedaa3400b006134559aa9f9494 100644 (file)
@@ -822,7 +822,6 @@ gtk_text_layout_draw (GtkTextLayout *layout,
                       GList **widgets)
 {
   gint offset_y;
-  GSList *cursor_list;
   GtkTextRenderer *text_renderer;
   GtkTextIter selection_start, selection_end;
   gboolean have_selection;
@@ -862,8 +861,6 @@ gtk_text_layout_draw (GtkTextLayout *layout,
       GtkTextLineDisplay *line_display;
       gint selection_start_index = -1;
       gint selection_end_index = -1;
-      gboolean have_strong;
-      gboolean have_weak;
 
       GtkTextLine *line = tmp_list->data;
 
@@ -905,47 +902,52 @@ gtk_text_layout_draw (GtkTextLayout *layout,
                        selection_start_index, selection_end_index);
 
           /* We paint the cursors last, because they overlap another chunk
-         and need to appear on top. */
-
-         have_strong = FALSE;
-         have_weak = FALSE;
-         
-         cursor_list = line_display->cursors;
-         while (cursor_list)
-           {
-             GtkTextCursorDisplay *cursor = cursor_list->data;
-             if (cursor->is_strong)
-               have_strong = TRUE;
-             else
-               have_weak = TRUE;
-             
-             cursor_list = cursor_list->next;
-           }
-         
-          cursor_list = line_display->cursors;
-          while (cursor_list)
+           * and need to appear on top.
+           */
+          if (line_display->cursors != NULL)
             {
-              GtkTextCursorDisplay *cursor = cursor_list->data;
-             GtkTextDirection dir;
-             GdkRectangle cursor_location;
-
-              dir = line_display->direction;
-             if (have_strong && have_weak)
-               {
-                 if (!cursor->is_strong)
-                   dir = (dir == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-               }
-             cursor_location.x = line_display->x_offset + cursor->x;
-             cursor_location.y = line_display->top_margin + cursor->y;
-             cursor_location.width = 0;
-             cursor_location.height = cursor->height;
+              int i;
 
-             gtk_draw_insertion_cursor (widget, cr, &cursor_location,
-                                         cursor->is_strong,
-                                         dir, have_strong && have_weak);
-
-              cursor_list = cursor_list->next;
+              for (i = 0; i < line_display->cursors->len; i++)
+                {
+                  int index;
+                  PangoRectangle strong_pos, weak_pos;
+                  GdkRectangle cursor_location;
+
+                  index = g_array_index(line_display->cursors, int, i);
+                  pango_layout_get_cursor_pos (line_display->layout, index, &strong_pos, &weak_pos);
+
+                  cursor_location.x = line_display->x_offset + PANGO_PIXELS (strong_pos.x);
+                  cursor_location.y = line_display->top_margin + PANGO_PIXELS (strong_pos.y);
+                  cursor_location.width = 0;
+                  cursor_location.height = PANGO_PIXELS (strong_pos.height);
+
+                  if (layout->cursor_direction == GTK_TEXT_DIR_NONE ||
+                      line_display->direction == layout->cursor_direction)
+                    {
+                      gtk_draw_insertion_cursor (widget, cr,
+                                                 &cursor_location, TRUE, line_display->direction,
+                                                 layout->cursor_direction != GTK_TEXT_DIR_NONE);
+                    }
+
+                  if ((strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y) &&
+                      (layout->cursor_direction == GTK_TEXT_DIR_NONE ||
+                       line_display->direction != layout->cursor_direction))
+                    {
+                      GtkTextDirection dir;
+
+                      dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+
+                      cursor_location.x = line_display->x_offset + PANGO_PIXELS (weak_pos.x);
+                      cursor_location.y = line_display->top_margin + PANGO_PIXELS (weak_pos.y);
+                      cursor_location.width = 0;
+                      cursor_location.height = PANGO_PIXELS (weak_pos.height);
+
+                      gtk_draw_insertion_cursor (widget, cr,
+                                                 &cursor_location, FALSE, dir,
+                                                 TRUE);
+                    }
+                }
             }
         } /* line_display->height > 0 */
           
index 7d48a3d05931ff8dfbaacad9587e5b73e85d05f0..a78886ab753108f4631c89d58c767377aa43f3a6 100644 (file)
@@ -827,8 +827,8 @@ gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
 
       if (cursors_only)
        {
-         g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
-         g_slist_free (display->cursors);
+          if (display->cursors)
+            g_array_free (display->cursors, TRUE);
          display->cursors = NULL;
          display->cursors_invalid = TRUE;
          display->has_block_cursor = FALSE;
@@ -1733,11 +1733,6 @@ add_cursor (GtkTextLayout      *layout,
             GtkTextLineSegment *seg,
             gint                start)
 {
-  PangoRectangle strong_pos, weak_pos;
-  GtkTextCursorDisplay *cursor = NULL; /* Quiet GCC */
-  gboolean add_weak = FALSE;
-  gboolean add_strong = FALSE;
-  
   /* Hide insertion cursor when we have a selection or the layout
    * user has hidden the cursor.
    */
@@ -1767,46 +1762,10 @@ add_cursor (GtkTextLayout      *layout,
        }
     }
 
-  pango_layout_get_cursor_pos (display->layout, start, &strong_pos, &weak_pos);
-
-  if (layout->cursor_direction == GTK_TEXT_DIR_NONE)
-    {
-      add_strong = TRUE;
-      add_weak = TRUE;
-    }
-  else if (display->direction == layout->cursor_direction)
-    add_strong = TRUE;
-  else
-    add_weak = TRUE;
+  if (!display->cursors)
+    display->cursors = g_array_new (FALSE, FALSE, sizeof(int));
 
-  if (add_strong)
-    {
-      cursor = g_new (GtkTextCursorDisplay, 1);
-
-      cursor->x = PANGO_PIXELS (strong_pos.x);
-      cursor->y = PANGO_PIXELS (strong_pos.y);
-      cursor->height = PANGO_PIXELS (strong_pos.height);
-      cursor->is_strong = TRUE;
-      cursor->is_weak = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
-      display->cursors = g_slist_prepend (display->cursors, cursor);
-    }
-  
-  if (add_weak)
-    {
-      if (weak_pos.x == strong_pos.x && add_strong)
-       cursor->is_weak = TRUE;
-      else
-       {
-         cursor = g_new (GtkTextCursorDisplay, 1);
-         
-         cursor->x = PANGO_PIXELS (weak_pos.x);
-         cursor->y = PANGO_PIXELS (weak_pos.y);
-         cursor->height = PANGO_PIXELS (weak_pos.height);
-         cursor->is_strong = (layout->cursor_direction == GTK_TEXT_DIR_NONE) ? FALSE : TRUE;
-         cursor->is_weak = TRUE;
-         display->cursors = g_slist_prepend (display->cursors, cursor);
-       }
-    }
+  display->cursors = g_array_append_val (display->cursors, start);
 }
 
 static gboolean
@@ -2530,10 +2489,7 @@ gtk_text_layout_free_line_display (GtkTextLayout      *layout,
         g_object_unref (display->layout);
 
       if (display->cursors)
-        {
-          g_slist_foreach (display->cursors, (GFunc)g_free, NULL);
-          g_slist_free (display->cursors);
-        }
+        g_array_free (display->cursors, TRUE);
 
       if (display->pg_bg_color)
         gdk_color_free (display->pg_bg_color);
index 78ec750c91695f1d6300a78c4805ea0f58e223f2..ed2556a86524d981b44169e6ba11a7abddb35793 100644 (file)
@@ -109,7 +109,6 @@ typedef struct _GtkTextLineData GtkTextLineData;
 typedef struct _GtkTextLayout         GtkTextLayout;
 typedef struct _GtkTextLayoutClass    GtkTextLayoutClass;
 typedef struct _GtkTextLineDisplay    GtkTextLineDisplay;
-typedef struct _GtkTextCursorDisplay  GtkTextCursorDisplay;
 typedef struct _GtkTextAttrAppearance GtkTextAttrAppearance;
 
 struct _GtkTextLayout
@@ -225,19 +224,11 @@ struct _GtkTextAttrAppearance
   PangoAttribute attr;
   GtkTextAppearance appearance;
 };
-struct _GtkTextCursorDisplay
-{
-  gint x;
-  gint y;
-  gint height;
-  guint is_strong : 1;
-  guint is_weak : 1;
-};
 
 struct _GtkTextLineDisplay
 {
   PangoLayout *layout;
-  GSList *cursors;
+  GArray *cursors;      /* indexes of cursors in the PangoLayout */
 
   GtkTextDirection direction;